import { TASK_RECORD_DB_PATH } from "../../constants";
import { defaultTaskRecordDBSchema } from "../../constants/schema";
import { BuildTaskParam, BuildTaskType } from "../model/BuildTask";
import { LowWithLodash } from "../model/DBWithLodash";
import { TaskResultStatus } from "../model/ListResult";
import dayjs from "dayjs";
import {
  BuildTaskRecord,
  BuildTaskStatus,
  TaskRecordDBSchema,
} from "../model/TaskRecordDBSchema";
import { DBService } from "./DBService";
import { supportTaskType } from "../../constants/command";
import { genId } from "../utils/genId";

/**
 * 职责描述：
 * 负责处理任务记录，包括增加、删除、查询、更新
 */
export class BuildTaskService extends DBService {
  #dbIns: LowWithLodash<TaskRecordDBSchema> | null = null;

  #normalizeParam(param: BuildTaskParam | BuildTaskRecord): BuildTaskRecord {
    if ((param as BuildTaskRecord).status) return param as BuildTaskRecord;
    const { taskList, taskTitle, taskDesc = "" } = param as BuildTaskParam;

    let allCount = 0;
    const _taskList = taskList
      .filter((v) => {
        return supportTaskType.includes(v.type);
      })
      .map(({ total, type }) => {
        allCount += total;
        return {
          suc: 0,
          fail: 0,
          rest: total,
          total,
          type,
        };
      });

    const rslt: BuildTaskRecord = {
      taskId: genId(),
      taskTitle,
      taskDesc,
      createTime: Date.now(),
      status: "pending",
      total: allCount,
      rest: allCount,
      taskList: _taskList,
    };
    return rslt;
  }

  async init() {
    const db = await super.init(TASK_RECORD_DB_PATH, defaultTaskRecordDBSchema);
    this.#dbIns = db;
    return db;
  }

  /**
   * 添加一条任务记录
   * @param param
   * @returns
   */
  async add(param: BuildTaskParam | BuildTaskRecord) {
    const rec = this.#normalizeParam(param);
    // 入库
    return await this.#dbIns?.update(({ data }) => {
      data.push(rec);
    });
  }

  /**
   * 查询任务记录
   * @param filter
   * @returns
   */
  async list(filter?: (value: BuildTaskRecord, index: number) => boolean) {
    // 记得深拷贝给外部使用
    return this.#dbIns?.chain.get("data").filter(filter).cloneDeep().value() || [];
  }

  /**
   * 查询单条满足条件的记录
   * @param filter
   * @returns
   */
  async find(filter?: (value: BuildTaskRecord, index: number) => boolean) {
    // 记得深拷贝给外部使用
    return this.#dbIns?.chain.get("data").find(filter).cloneDeep().value();
  }

  async updateTaskStatus(param: {
    taskId: string;
    status?: BuildTaskStatus;
    startTime?: number;
    endTime?: number;
  }) {
    const { taskId, status, startTime, endTime } = param;
    return await this.#dbIns?.update(({ data }) => {
      // 找到对应的任务
      const rec = data.find((v) => {
        return v.taskId === taskId;
      });
      if (rec) {
        rec.status = status || rec.status;
        rec.startTime = startTime || rec.startTime;
        rec.endTime = endTime || rec.endTime;
      }
    });
  }

  /**
   * 当一个任务完成时，调用此方法
   * @param param
   * @returns
   */
  async updateTaskRest(param: {
    taskId: string;
    type: BuildTaskType;
    status: TaskResultStatus;
  }) {
    const { taskId, type, status } = param;
    return await this.#dbIns?.update(({ data }) => {
      // 找到对应的任务
      const rec = data.find((v) => {
        return v.taskId === taskId;
      });
      // 无任务或者任务已完成则返回
      if (!rec || rec.status === "finish") return;
      // 找到对应类型的任务
      const taskInfo = rec?.taskList.find((v) => {
        return v.type === type;
      });
      // 阻止异常的变化
      if (!taskInfo?.rest || taskInfo.rest <= 0) return;
      if (status === "success") {
        // 任务执行成功
        taskInfo.suc += 1;
      } else {
        // 任务执行失败
        taskInfo.fail += 1;
      }
      // 对应任务统计-1
      taskInfo.rest -= 1;
      // 总剩余-1
      rec.rest -= 1;
      if (rec.rest <= 0) {
        // 无总的剩余，设置为完成状态
        rec.status = "finish";
      } else {
        // 设置为进行态
        rec.status = "running";
      }
    });
  }

  /**
   * 清理所有数据，慎用
   * @returns
   */
  async clearAll() {
    return await this.#dbIns?.update((v) => {
      v.data = [];
    });
  }

  /**
   * 删除指定任务
   * @param taskId
   * @returns
   */
  async deleteById(taskId: string) {
    return await this.#dbIns?.update((v) => {
      v.data = v.data.filter((val) => val.taskId !== taskId);
    });
  }
}

export const buildTaskService = new BuildTaskService();
